package physicsSimTest;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

import javax.swing.JPanel;
import javax.swing.Timer;

public class PhysPanel extends JPanel {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	public HashMap<Integer, Particle> partMap = new HashMap<Integer, Particle>();
	private long lastFrame = 0;
	int index = 1000;
	public final double SIMSPEED = 1;
	public final double RUNSPEED = 1;
	double oldEnergy = 1000000;

	public PhysPanel(){
		this.setSize(1000, 1000);
		this.setBackground(Color.BLACK);
		//partMap.put(1, new Particle(1, Math.random()*900+25, Math.random()*500+250, 0, 0, 20));
		//partMap.put(2, new Particle(2, Math.random()*900+25, Math.random()*500+250, 0, 0, 20));
		/*partMap.put(1, new Particle(1, Math.random()*900+25, Math.random()*500+250, Math.random()*2-1, Math.random()*2-1, 20));
		partMap.put(2, new Particle(2, Math.random()*900+25, Math.random()*500+250, Math.random()*2-1, Math.random()*2-1, 20));
		partMap.put(3, new Particle(3, Math.random()*900+25, Math.random()*500+250, Math.random()*2-1, Math.random()*2-1, 20));
		partMap.put(4, new Particle(4, Math.random()*500+250, Math.random()*500+250, Math.random()*2-1, Math.random()*2-1, 20));
		partMap.put(5, new Particle(5, Math.random()*500+250, Math.random()*500+250, Math.random()*2-1, Math.random()*2-1, 20));
		partMap.put(6, new Particle(6, Math.random()*500+250, Math.random()*500+250, Math.random()*2-1, Math.random()*2-1, 20));
		partMap.put(7, new Particle(7, Math.random()*900+25, Math.random()*500+250, Math.random()*2-1, Math.random()*2-1, 20));
		partMap.put(8, new Particle(8, Math.random()*900+25, Math.random()*500+250, Math.random()*2-1, Math.random()*2-1, 20));
		partMap.put(9, new Particle(9, Math.random()*900+25, Math.random()*500+250, Math.random()*2-1, Math.random()*2-1, 20));
		partMap.put(10, new Particle(10, Math.random()*500+250, Math.random()*500+250, Math.random()*2-1, Math.random()*2-1, 20));
		partMap.put(11, new Particle(11, Math.random()*500+250, Math.random()*500+250, Math.random()*2-1, Math.random()*2-1, 20));*/
		for(int i = 0; i<6; i++)
			partMap.put(i, new Particle(i, Math.random()*900+25, Math.random()*500+250, Math.random()*2-1, Math.random()*2-1, 20));
		partMap.get(0).col = new Color(255, 0, 0);
		//partMap.put(12, new Particle(12, Math.random()*500+250, Math.random()*500+250, Math.random()*2-1, Math.random()*2-1, 10));

		Timer t = new Timer(1000/(int)(64*RUNSPEED), new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent arg0) {
				runLogic();
				//System.out.println("hi");
			}

		});
		getDelta();
		t.start();
	}

	protected void runLogic() {
		//partMap.put(index, new Particle(index, Math.random()*900+25, Math.random()*500+250, Math.random()*2-1, Math.random()*2-1, 1));
		//index++;
		//if(index%100==0)
		//System.out.println(index);

		float delta = getDelta(); //change in time
		delta = (float) (delta);
		System.out.println(delta);
		//System.out.println(delta);

		for(Integer i: partMap.keySet()){
			partMap.get(i).resetVelocity();
		}
		for(Integer i: partMap.keySet()){
			for(Integer j: partMap.keySet()){
				if(i<j){
					float magnitude = (float) ((delta+i)/partMap.keySet().size());
					partMap.get(i).forceTo(partMap.get(j).getPosVector(), magnitude);
					partMap.get(j).forceTo(partMap.get(i).getPosVector(), magnitude);

					//partMap.get(i).forceFromSquared(partMap.get(j).getPosVector(), (float) ((delta+j)*50));
					//partMap.get(j).forceFromSquared(partMap.get(i).getPosVector(), (float) ((delta+j)*50));
				}
			}

		}
		boolean reset = true;
		while(reset){
			reset = false;
			SortedSet<Collision> cSet = new TreeSet<Collision>();
			for(Integer i: partMap.keySet()){
				for(Integer j: partMap.keySet()){
					
					if(i<j){
						Collision c = partMap.get(i).collide(partMap.get(j), delta);
						if(c!=null){
							cSet.add(c);
							reset = true;
						}
					}
				}

			}
			int i = 0;
			for(Collision c: cSet){
				if(i!=0){
					System.out.println("T"+(i+1)+": "+c.time);
					i++;
					continue;
				}
				c.runCollide();
				System.out.println("T1: "+c.time);
				i++;
			}
		}

		for(Integer i: partMap.keySet()){
			partMap.get(i).airResist(delta);
			partMap.get(i).roundDownVelocity(3);
		}
		for(Integer i: partMap.keySet()){
			partMap.get(i).move(delta, partMap);
		}
		double energy = 0;
		for(Integer i: partMap.keySet()){
			energy+=Vector.getMagnitude(partMap.get(i).getActualVelocity());
		}
		if(oldEnergy==1000000)
			oldEnergy=energy;
		else if(Math.round(energy/oldEnergy*1000)/1000.0!=0.996){
			//System.out.println("Energy: "+energy);
			//System.out.println("Energy %: "+energy/oldEnergy*100);
		}
		oldEnergy=energy;
		repaint();
	}

	/** 
	 * Calculate how many milliseconds have passed 
	 * since last frame.
	 * 
	 * @return milliseconds passed since last frame 
	 */
	public int getDelta() {
		long time = getTime();
		int delta = (int) (time - lastFrame );
		lastFrame = time;

		return delta;
	}

	/**
	 * Get the accurate system time
	 * 
	 * @return The system time in milliseconds
	 */
	public long getTime() {
		return (System.nanoTime())/1000000;
	}

	public void paint(Graphics g){
		g.setColor(Color.BLACK);
		g.fillRect(0, 0, 1200, 1200);
		for(Integer i: partMap.keySet())
			partMap.get(i).paint(g);
	}

}
